﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Text;
using System.Threading;
using Android.Graphics;
using Android.Graphics.Drawable;
using Android.Util;
using LeePong.Game.Entities;
using LeePong.Game.Shapes;

namespace LeePong.Android.Drawing
{
    public class DrawingManager
    {
        private GameSurface _surface;
        private BitmapDrawable _ballFuildDrawable;

        private BitmapDrawable _ballDrawable;
        private BitmapDrawable _raquetDrawable;
        private BitmapDrawable _landDrawable;

        public bool ShowShadowBalls;
        private const int SHADOW_COUNT = 3;
        private List<RectF> _shadowBalls = new List<RectF>();
        private Paint _ballPaint = new Paint();
        private Paint _textPaint = new Paint();
        private Paint _fpsPaint = new Paint();

        public bool ShowFps;
        public int DesiredFpsValue;
        private double _currentFps;
        private int _fpsSleepPeriod = 3;
        private Stopwatch _fpsWatch = new Stopwatch();
        private int _fpsCounter;

        public DrawingManager(GameSurface surface)
        {
            this._surface = surface;

            var ressources = _surface.Context.GetResources();

            var set = new BitmapFactory.Options() { InScaled = true };
            _ballFuildDrawable = new BitmapDrawable(ressources, BitmapFactory.DecodeResource(ressources, R.Drawables.soccer_fluid, set));
            _ballDrawable = new BitmapDrawable(ressources, BitmapFactory.DecodeResource(ressources, R.Drawables.soccer, set));
            _raquetDrawable = new BitmapDrawable(ressources, BitmapFactory.DecodeResource(ressources, R.Drawables.Racket, set));
            _landDrawable = new BitmapDrawable(ressources, BitmapFactory.DecodeResource(ressources, R.Drawables.LandTexture, set));


            _textPaint.SetARGB(150, 255, 255, 255);
            _textPaint.SetTypeface(Typeface.DEFAULT_BOLD);
            _textPaint.SetTextAlign(Paint.Align.CENTER);

            _fpsPaint.SetARGB(255, 40, 200, 200);
            _fpsPaint.SetTextSize(40);
        }

        public void Init()
        {
            _textPaint.SetTextSize(_surface.Engine.LeftScore.Rect.Height);
        }

        public void DoDraw(Canvas canvas)
        {
            var engine = this._surface.Engine;
            canvas.DrawBitmap(_landDrawable.Bitmap, null, engine.Land.Rect.ToRectF(), null);

            //canvas.DrawColor(Color.BLACK);
            DrawScore(canvas, engine.LeftScore);
            DrawScore(canvas, engine.RightScore);

            canvas.DrawBitmap(_raquetDrawable.Bitmap, null, engine.LeftRacket.Rect.ToRectF(), null);
            canvas.DrawBitmap(_raquetDrawable.Bitmap, null, engine.RightRacket.Rect.ToRectF(), null);

            var ballrect = engine.Ball.Rect.ToRectF();
            DrawShadowBalls(canvas, ballrect);

            HandleFps(canvas);
        }

        private void HandleFps(Canvas canvas)
        {
            Thread.Sleep(_fpsSleepPeriod);

            if (!ShowFps && DesiredFpsValue == 0)
                return;

            _fpsCounter++;
            if (_fpsCounter == 100)
            {
                _currentFps = 100.0 / (_fpsWatch.ElapsedMilliseconds / 1000.0);
                Log.D("----", "draw fps" + _currentFps);
                _fpsWatch.Restart();
                _fpsCounter = 0;

                if (DesiredFpsValue > 0)
                {
                    var diff = _currentFps - DesiredFpsValue;
                    if (diff < 0)
                        _fpsSleepPeriod = _fpsSleepPeriod <= 1 ? 1 : _fpsSleepPeriod - 1;
                    else
                    {
                        _fpsSleepPeriod++;
                    }
                }
            }

            if (ShowFps)
                DrawFps(canvas, _currentFps);
        }

        private void DrawFps(Canvas canvas, double fps)
        {
            var x = 60;
            var y = 60;

            canvas.Save();
            canvas.Rotate(-90, x, y);
            canvas.DrawText(fps.ToString(CultureInfo.InvariantCulture), x, y, _fpsPaint);
            canvas.Restore();
        }

        private void DrawScore(Canvas canvas, Score score)
        {

            _textPaint.SetARGB(100 + score.Glow, 255, 255, 255);

            canvas.Save();
            canvas.Rotate(-90, score.Rect.X, score.Rect.Y);
            canvas.DrawText(score.Points.ToString(CultureInfo.InvariantCulture), score.Rect.X, score.Rect.Y, _textPaint);
            canvas.Restore();
        }

        private void DrawShadowBalls(Canvas canvas, RectF lastRec)
        {
            var drawable = _ballDrawable;
            var ball = this._surface.Engine.Ball;

            if (ball.Speed > 4)
            {
                drawable = _ballDrawable;
            }

            //canvas.Save();
            //canvas.Rotate(ball.Angle + 90, ball.Rect.CenterX, ball.Rect.CenterY);
            canvas.DrawBitmap(drawable.Bitmap, null, lastRec, null);
            // canvas.Restore();

            if (!ShowShadowBalls)
            {
                return;
            }

            //for (int i = 0; i < _shadowBalls.Count; i++)
            //{
            //    var alpha = (40 / SHADOW_COUNT) * (i + 1);

            //    _ballPaint.SetAlpha(alpha);
            //    var re = _shadowBalls[i];
            //    //canvas.Save();
            //    //canvas.Rotate(ball.Angle + 90, re.CenterX(), re.CenterY());
            //    canvas.DrawBitmap(drawable.Bitmap, null, re, _ballPaint);
            //    //canvas.Restore();
            //}


            //if (_shadowBalls.Count == SHADOW_COUNT)
            //{
            //    _shadowBalls.RemoveAt(0);

            //}
            //_shadowBalls.Insert(_shadowBalls.Count, lastRec);
        }
    }
}
